/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Constian {
    public static final int LOOP_MAX = 50;
    public static final int VARRAY_LENGHT = 9;
    public static final int NORMAL_LENGHT = 6;
    public static final int HALF_NUMBER = 2;
    public static final int ARRAY_MAX_COUNT_FOUR = 4;
    public static final int ARRAY_MAX_COUNT_THR = 3;
    public static final int ARRAY_INDEX_TWO = 2;
    public static final int ARRAY_INDEX_THREE = 3;
    public static final int ARRAY_INDEX_FIVE = 5;
    public static final int ARRAY_INDEX_SIX = 6;
    public static final int ARRAY_INDEX_EIGHT = 8;
    public static final int ARRAY_INDEX_SEVEN = 7;
    public static final int ARRAY_INDEX_NINE = 9;
    public static final int ARRAY_INDEX_TEN = 10;
    public static final int ARRAY_INDEX_ELEVEN = 11;
    public static final int LINEAR_MEASURE = 180;
    public static final int VALIDATION_TWENTY = 20;
    public static final double VALIDATION_TWENTY_VALUE = 2889.0000000000045;
    public static final int VALIDATION_FORTY = 40;
    public static final double VALIDATION_FORTY_VALUE = 2889.0000000000055;
    public static final int VALIDATION_EIGHT = 80;
    public static final double VALIDATION_EIGHT_VALUE = 2889.000000000005;
    public static final int VALIDATION_OHS = 160;
    public static final double VALIDATION_OHS_VALUE = 2889.0000000000055;
    public static final int QARRAY_ONE_VALUE = 150;
    public static final int TIME_UNIT = 1000;
    public static final int TIME_COUNT = 9;
    public static final int DRAW_QUBE_COUNT = 5;
}

class Object2 {
    public double[] v;
}
class Object1 {
    public int loopCount = 0;
    public int loopMax = Constian.LOOP_MAX;
    public int timeMax = 0;
    public int timeAvg = 0;
    public int timeMin = 0;
    public int timeTemp = 0;
    public int timeTotal = 0;
    public boolean init = false;
}

class CreateP {
    public double[] v;

    CreateP(double x, double y, double z) {
        this.v = new double[]{x, y, z, 1};
    }
}

class Q {
    public CreateP[] vArray = new CreateP[Constian.VARRAY_LENGHT];
    public double[][] edge;
    public double[][] normal = new double[Constian.NORMAL_LENGHT][];
    public boolean[] line;
    public int numPx = 0;
    public int lastPx = 0;

}

class ThreeCube {

    public int util(double z1, double z2) {
        if (z2 >= z1) {
            return 1;
        } else {
            return -1;
        }
    }

    public void drawLine(CreateP from, CreateP to) {
        double x1 = from.v[0];
        double x2 = to.v[0];
        double y1 = from.v[1];
        double y2 = to.v[1];
        double dx = Math.abs(x2 - x1);
        double dy = Math.abs(y2 - y1);
        double x = x1;
        double y = y1;
        double incX1;
        double incY1;
        double incX2;
        double incY2;
        double den;
        double num;
        double numAdd;
        int numPix;

        incX1 = this.util(x1, x2);
        incX2 = incX1;
        incY1 = this.util(y1, y2);
        incY2 = incY1;

        if (dx >= dy) {
            incX1 = 0;
            incY2 = 0;
            den = dx;
            num = dx / Constian.HALF_NUMBER;
            numAdd = dy;
            numPix = (int) dx;
        } else {
            incX2 = 0;
            incY1 = 0;
            den = dy;
            num = dy / Constian.HALF_NUMBER;
            numAdd = dx;
            numPix = (int) dy;
        }
        numPix = this.q.lastPx + numPix;

        for (int i = this.q.lastPx; i < numPix; i++) {
            num += numAdd;
            if (num >= den) {
                x += incX1;
                y += incY1;
            }
            x += incX2;
            y += incY2;
        }
        this.q.lastPx = numPix;
    }

    public double[] calcCross(double[] v0, double[] v1) {
        double[] cross = new double[]{0, 0, 0, 0};
        cross[0] = v0[1]*v1[Constian.ARRAY_INDEX_TWO] - v0[Constian.ARRAY_INDEX_TWO]*v1[1];
        cross[1] = v0[Constian.ARRAY_INDEX_TWO]*v1[0] - v0[0]*v1[Constian.ARRAY_INDEX_TWO];
        cross[Constian.ARRAY_INDEX_TWO] = v0[0]*v1[1] - v0[1]*v1[0];
        return cross;
    }

    public double[] calcNormal(double[] v0, double[] v1, double[] v2) {
        double[] a = new double[]{0, 0, 0, 0};
        double[] b = new double[]{0, 0, 0, 0};
        for (int i = 0; i < Constian.ARRAY_MAX_COUNT_THR; i++) {
            a[i] = v0[i] - v1[i];
            b[i] = v2[i] - v1[i];
        }
        a = calcCross(a, b);
        double x = a[0]*a[0] + a[1]*a[1] + a[Constian.ARRAY_INDEX_TWO]*a[Constian.ARRAY_INDEX_TWO];
        double Length = Math.sqrt(x);
        for (int i = 0; i < Constian.ARRAY_MAX_COUNT_THR; i++) {
            a[i] = a[i] / Length;
        }
        a[Constian.ARRAY_INDEX_THREE] = 1;
        return a;
    }
    public double[][] mMulti(double[][] m1, double[][] m2) {
        double[][] m = new double[][]{
                new double[]{0, 0, 0, 0},
                new double[]{0, 0, 0, 0},
                new double[]{0, 0, 0, 0},
                new double[]{0, 0, 0, 0}
        };
        for (int i = 0; i < Constian.ARRAY_MAX_COUNT_FOUR; i++) {
            for (int j = 0; j < Constian.ARRAY_MAX_COUNT_FOUR; j++) {
                m[i][j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j] + m1[i][Constian.ARRAY_INDEX_TWO] * m2[Constian.ARRAY_INDEX_TWO][j] + m1[i][Constian.ARRAY_INDEX_THREE] * m2[Constian.ARRAY_INDEX_THREE][j];
            }
        }
        return m;
    }

    public double[] vMulti(double[][] m, double[] v) {
        double[] vect = new double[]{0, 0, 0, 0};
        for (int i = 0; i < Constian.ARRAY_MAX_COUNT_FOUR; i++) {
            vect[i] = m[i][0] * v[0] + m[i][1] * v[1] + m[i][Constian.ARRAY_INDEX_TWO] * v[Constian.ARRAY_INDEX_TWO] + m[i][Constian.ARRAY_INDEX_THREE] * v[Constian.ARRAY_INDEX_THREE];
        }
        return  vect;
    }

    public List<Double> vMulti2(double[][] m, double[] v) {
        List<Double> vect = new ArrayList<>();
        for (int i = 0; i < Constian.ARRAY_MAX_COUNT_FOUR; i++) {
            vect.add(m[i][0] * v[0] + m[i][1] * v[1] + m[i][Constian.ARRAY_INDEX_TWO] * v[Constian.ARRAY_INDEX_TWO]);
        }
        return  vect;
    }

    public double[][] translate(double[][] m, double dx, double dy, double dz) {
        double[][] t = new double[][]{
                new double[]{1,0,0,dx},
                new double[]{0,1,0,dy},
                new double[]{0,0,1,dz},
                new double[]{0,0,0,1},
        };
        return this.mMulti(t, m);
    }

    public double[][] rotateX(double[][] m, double phi) {
        double a = phi;
        a *= Math.PI / Constian.LINEAR_MEASURE;
        double cos = Math.cos(a);
        double sin = Math.sin(a);
        double[][] R = new double[][]{
                new double[]{1,0,0,0},
                new double[]{0,cos,-sin,0},
                new double[]{0,sin,cos,0},
                new double[]{0,0,0,1}
        };
        return this.mMulti(R, m);
    }

    public double[][] rotateY(double[][] m, double phi) {
        double a = phi;
        a *= Math.PI / Constian.LINEAR_MEASURE;
        double cos = Math.cos(a);
        double sin = Math.sin(a);
        double[][] r = new double[][]{
                new double[]{cos, 0, sin, 0},
                new double[]{0, 1, 0, 0},
                new double[]{-sin, 0, cos, 0},
                new double[]{0, 0, 0, 1}
        };
        return this.mMulti(r, m);
    }

    public double[][] rotateZ(double[][] m, double phi) {
        double a = phi;
        a *= Math.PI / Constian.LINEAR_MEASURE;
        double cos = Math.cos(a);
        double sin = Math.sin(a);
        double[][] r = new double[][]{
                new double[]{cos, -sin, 0, 0},
                new double[]{sin, cos, 0, 0},
                new double[]{0, 0, 1, 0},
                new double[]{0, 0, 0, 1}
        };
        return this.mMulti(r, m);
    }

    public void drawLine1(ArrayList<List<Double>> curN) {
        if (curN.get(0).get(Constian.ARRAY_INDEX_TWO) < 0) {
            if (!this.q.line[0]) {
                this.drawLine(this.q.vArray[0], this.q.vArray[1]);
                this.q.line[0] = true;
            }
            if (!this.q.line[1]) {
                this.drawLine(this.q.vArray[1], this.q.vArray[Constian.ARRAY_INDEX_TWO]);
                this.q.line[1] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_TWO]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_TWO], this.q.vArray[Constian.ARRAY_INDEX_TWO]);
                this.q.line[Constian.ARRAY_INDEX_TWO] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_TWO]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_THREE], this.q.vArray[0]);
                this.q.line[Constian.ARRAY_INDEX_TWO] = true;
            }
        }

        if (curN.get(1).get(Constian.ARRAY_INDEX_TWO) < 0) {
            if (!this.q.line[Constian.ARRAY_INDEX_TWO]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_THREE], this.q.vArray[Constian.ARRAY_INDEX_TWO]);
                this.q.line[Constian.ARRAY_INDEX_TWO] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_NINE]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_THREE], this.q.vArray[Constian.ARRAY_INDEX_SIX]);
                this.q.line[Constian.ARRAY_INDEX_NINE] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_SIX]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_SIX], this.q.vArray[Constian.ARRAY_INDEX_SEVEN]);
                this.q.line[Constian.ARRAY_INDEX_SIX] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_TEN]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_SEVEN], this.q.vArray[Constian.ARRAY_INDEX_THREE]);
                this.q.line[Constian.ARRAY_INDEX_TEN] = true;
            }
        }
    }

    public void drawLine2(ArrayList<List<Double>> curN) {
        if (curN.get(Constian.ARRAY_INDEX_THREE).get(Constian.ARRAY_INDEX_THREE) < 0) {
            if (!this.q.line[Constian.ARRAY_MAX_COUNT_FOUR]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_MAX_COUNT_FOUR], this.q.vArray[Constian.ARRAY_INDEX_FIVE]);
                this.q.line[Constian.ARRAY_MAX_COUNT_FOUR] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_FIVE]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_FIVE], this.q.vArray[Constian.ARRAY_INDEX_SIX]);
                this.q.line[Constian.ARRAY_INDEX_FIVE] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_SIX]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_SIX], this.q.vArray[Constian.ARRAY_INDEX_SEVEN]);
                this.q.line[Constian.ARRAY_INDEX_SIX] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_SEVEN]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_SEVEN], this.q.vArray[Constian.ARRAY_MAX_COUNT_FOUR]);
                this.q.line[Constian.ARRAY_INDEX_SEVEN] = true;
            }
        }
        if (curN.get(Constian.ARRAY_INDEX_THREE).get(Constian.ARRAY_INDEX_THREE) < 0) {
            if (!this.q.line[Constian.ARRAY_MAX_COUNT_FOUR]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_MAX_COUNT_FOUR], this.q.vArray[Constian.ARRAY_INDEX_FIVE]);
                this.q.line[Constian.ARRAY_MAX_COUNT_FOUR] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_EIGHT]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_FIVE], this.q.vArray[1]);
                this.q.line[Constian.ARRAY_INDEX_EIGHT] = true;
            }
            if (!this.q.line[0]) {
                this.drawLine(this.q.vArray[1], this.q.vArray[0]);
                this.q.line[0] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_ELEVEN]) {
                this.drawLine(this.q.vArray[0], this.q.vArray[Constian.ARRAY_MAX_COUNT_FOUR]);
                this.q.line[Constian.ARRAY_INDEX_ELEVEN] = true;
            }
        }
    }

    public void drawQube() {
        ArrayList<List<Double>> curN = new ArrayList<List<Double>>();
        this.q.lastPx = 0;
        for (int i = Constian.DRAW_QUBE_COUNT; i >= 0; i--) {
            curN.add(this.vMulti2(this.mQube, this.q.normal[i]));
        }
        this.drawLine1(curN);
        this.drawLine2(curN);
        if (curN.get(Constian.ARRAY_MAX_COUNT_FOUR).get(Constian.ARRAY_INDEX_TWO) < 0) {
            if (!this.q.line[Constian.ARRAY_INDEX_ELEVEN]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_MAX_COUNT_FOUR], this.q.vArray[0]);
                this.q.line[Constian.ARRAY_INDEX_ELEVEN] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_THREE]) {
                this.drawLine(this.q.vArray[0], this.q.vArray[Constian.ARRAY_INDEX_THREE]);
                this.q.line[Constian.ARRAY_INDEX_THREE] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_TEN]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_THREE], this.q.vArray[Constian.ARRAY_INDEX_SEVEN]);
                this.q.line[Constian.ARRAY_INDEX_TEN] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_SEVEN]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_SEVEN], this.q.vArray[Constian.ARRAY_MAX_COUNT_FOUR]);
                this.q.line[Constian.ARRAY_INDEX_SEVEN] = true;
            }
        }
        if (curN.get(Constian.ARRAY_INDEX_FIVE).get(Constian.ARRAY_INDEX_TWO) < 0) {
            if (!this.q.line[Constian.ARRAY_INDEX_EIGHT]) {
                this.drawLine(this.q.vArray[1], this.q.vArray[Constian.ARRAY_INDEX_FIVE]);
                this.q.line[Constian.ARRAY_INDEX_EIGHT] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_FIVE]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_FIVE], this.q.vArray[Constian.ARRAY_INDEX_SIX]);
                this.q.line[Constian.ARRAY_INDEX_FIVE] = true;
            }
            if (!this.q.line[Constian.ARRAY_INDEX_NINE]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_SIX], this.q.vArray[Constian.ARRAY_INDEX_TWO]);
                this.q.line[Constian.ARRAY_INDEX_NINE] = true;
            }
            if (!this.q.line[1]) {
                this.drawLine(this.q.vArray[Constian.ARRAY_INDEX_TWO], this.q.vArray[1]);
                this.q.line[1] = true;
            }
        }
        this.q.line = new boolean[]{false,false,false,false,false,false,false,false,false,false,false,false};
        this.q.lastPx = 0;
    }

    public void loop() {
        if (testing.loopCount > testing.loopMax) {
            return;
        }
        String testingStr = String.valueOf(testing.loopCount);
        while (testingStr.length() < Constian.ARRAY_MAX_COUNT_THR) {
            testingStr = "0" + testingStr;
        }
        this.mTrans = translate(
                this.i,
                -this.q.vArray[Constian.ARRAY_INDEX_EIGHT].v[0],
                -this.q.vArray[Constian.ARRAY_INDEX_EIGHT].v[1],
                -this.q.vArray[Constian.ARRAY_INDEX_EIGHT].v[Constian.ARRAY_INDEX_TWO]
        );
        this.mTrans = this.rotateX(this.mTrans, 1);
        this.mTrans = this.rotateY(this.mTrans, Constian.ARRAY_MAX_COUNT_THR);
        this.mTrans = this.rotateZ(this.mTrans, Constian.ARRAY_INDEX_FIVE);
        this.mTrans = this.translate(
                this.mTrans,
                this.q.vArray[Constian.ARRAY_INDEX_EIGHT].v[0],
                this.q.vArray[Constian.ARRAY_INDEX_EIGHT].v[1],
                this.q.vArray[Constian.ARRAY_INDEX_EIGHT].v[Constian.ARRAY_INDEX_TWO]
        );
        this.mQube = this.mMulti(this.mTrans, this.mQube);
        for (int i = 8; i >= 0; i--) {
            this.q.vArray[i].v = this.vMulti(this.mTrans, this.q.vArray[i].v);
        }
        this.drawQube();
        this.testing.loopCount += 1;
        this.loop();
    }

    public Q q = new Q();
    // transformation matrix
    public double[][] mTrans;
    // position information of qube
    public double[][] mQube;
    // entity matrix
    public double[][] i;
    public Object2 origin = new Object2();
    public Object1 testing = new Object1();

    public Map<Integer, Double> validation = new HashMap<>();

    public ThreeCube() {
        this.validation.put(Constian.VALIDATION_TWENTY, Constian.VALIDATION_TWENTY_VALUE);
        this.validation.put(Constian.VALIDATION_FORTY, Constian.VALIDATION_FORTY_VALUE);
        this.validation.put(Constian.VALIDATION_EIGHT, Constian.VALIDATION_EIGHT_VALUE);
        this.validation.put(Constian.VALIDATION_OHS, Constian.VALIDATION_OHS_VALUE);
    }

    public void creat1(double CubeSize) {
        this.origin.v = new double[]{Constian.QARRAY_ONE_VALUE, Constian.QARRAY_ONE_VALUE, Constian.VALIDATION_TWENTY, 1};
        this.testing.loopCount = 0;
        this.testing.loopMax = Constian.LOOP_MAX;
        this.testing.timeMax = 0;
        this.testing.timeAvg = 0;
        this.testing.timeMin = 0;
        this.testing.timeTemp = 0;
        this.testing.timeTotal = 0;
        this.testing.init = false;

        this.mTrans = new double[][]{
                new double[]{1,0,0,0},
                new double[]{0,1,0,0},
                new double[]{0,0,1,0},
                new double[]{0,0,0,1}
        };

        this.mQube = new double[][]{
                new double[]{1,0,0,0},
                new double[]{0,1,0,0},
                new double[]{0,0,1,0},
                new double[]{0,0,0,1}
        };
        this.i = new double[][]{
                new double[]{1,0,0,0},
                new double[]{0,1,0,0},
                new double[]{0,0,1,0},
                new double[]{0,0,0,1}
        };
        // create qube
        this.q.vArray[0] = new CreateP(-CubeSize, -CubeSize, CubeSize);
        this.q.vArray[1] = new CreateP(-CubeSize, CubeSize, CubeSize);
        this.q.vArray[Constian.ARRAY_INDEX_TWO] = new CreateP(CubeSize, CubeSize, CubeSize);
        this.q.vArray[Constian.ARRAY_INDEX_THREE] = new CreateP(CubeSize, -CubeSize, CubeSize);
        this.q.vArray[Constian.ARRAY_MAX_COUNT_FOUR] = new CreateP(-CubeSize, -CubeSize, -CubeSize);
        this.q.vArray[Constian.ARRAY_INDEX_FIVE] = new CreateP(-CubeSize, CubeSize, -CubeSize);
        this.q.vArray[Constian.ARRAY_INDEX_SIX] = new CreateP(CubeSize, CubeSize, -CubeSize);
        this.q.vArray[Constian.ARRAY_INDEX_SEVEN] = new CreateP(CubeSize, -CubeSize, -CubeSize);
        this.q.vArray[Constian.ARRAY_INDEX_EIGHT] = new CreateP(0, 0, 0);
    }

    public void create2(double CubeSize) {
        // anti-clockwise edge check
        this.q.edge = new double[][]{
                new double[]{0,1,Constian.ARRAY_INDEX_TWO},
                new double[]{Constian.ARRAY_INDEX_THREE,Constian.ARRAY_INDEX_TWO,Constian.ARRAY_INDEX_SIX},
                new double[]{Constian.ARRAY_INDEX_SEVEN, Constian.ARRAY_INDEX_SIX, Constian.ARRAY_INDEX_FIVE},
                new double[]{Constian.ARRAY_MAX_COUNT_FOUR, Constian.ARRAY_INDEX_FIVE, 1},
                new double[]{Constian.ARRAY_MAX_COUNT_FOUR, 0, Constian.ARRAY_INDEX_THREE},
                new double[]{1, Constian.ARRAY_INDEX_FIVE, Constian.ARRAY_INDEX_SIX},
        };

        for (int i = 0; i < this.q.edge.length; i++) {
            this.q.normal[i] = this.calcNormal(
                    this.q.vArray[(int) this.q.edge[i][0]].v,
                    this.q.vArray[(int) this.q.edge[i][1]].v,
                    this.q.vArray[(int) this.q.edge[i][Constian.ARRAY_INDEX_TWO]].v
            );
        }
        this.q.line = new boolean[]{false,false,false,false,false,false,false,false,false,false,false,false};
        this.q.numPx = (int) (Constian.ARRAY_INDEX_NINE * Constian.ARRAY_INDEX_TWO * CubeSize);
        for (int i = 0; i < this.q.numPx; i++) {
            new CreateP(0, 0, 0);
        }
        this.mTrans = translate(this.mTrans, this.origin.v[0], this.origin.v[1], this.origin.v[Constian.ARRAY_INDEX_TWO]);
        this.mQube = mMulti(this.mTrans, this.mQube);
        for (int i = 0; i < Constian.TIME_COUNT; i++) {
            this.q.vArray[i].v = vMulti(mTrans, q.vArray[i].v);
        }
        this.drawQube();
        this.testing.init = true;
        this.loop();
    }

    public void create(double cubeSize) {
        this.creat1(cubeSize);
        this.create2(cubeSize);
//        System.out.print("CubeSize is " + cubeSize + ", mTrans value is " + this.mTrans[0][0]+ " " + this.mTrans[0][1]+ " " + this.mTrans[0][2] + " " + this.mTrans[0][3] + "\n");
//        System.out.print("CubeSize is " + cubeSize + ", mQube value is " + this.mQube[0][0] + " " + this.mQube[0][1] + " " + this.mQube[0][2] + " " + this.mQube[0][3] + "\n");

        double sum = 0;
        for (int i = 0; i < this.q.vArray.length; i++) {
            double[] vector = this.q.vArray[i].v;
            for (int j = 0; j < vector.length; j++) {
                sum += vector[j];
            }
        }
        if (sum != this.validation.get((int)cubeSize)) {
            //debugLog("Error: bad vector sum for cubeSize = " + cubeSize + "; expected " + this.validation.get(cubeSize) + " but got " + sum)
        }
    }

    public void runTest() {
        int i = Constian.VALIDATION_TWENTY;
        while (i <= Constian.VALIDATION_OHS) {
            this.create(i);
            i *= Constian.ARRAY_INDEX_TWO;
        }
    }

}

class Benchmark {

    public static void main(String[] args) {
        Benchmark benchmark = new Benchmark();
        benchmark.runIterationTime();
    }

    public void runIterationTime() {

        long beginTime = System.nanoTime();
        ThreeCube cube = new ThreeCube();
        for (int i = 0; i < Constian.ARRAY_INDEX_EIGHT; i++) {
            cube.runTest();
        }
        long endTime = System.nanoTime();
        System.out.print("3d-cube: ms = " + (endTime - beginTime) / (1000.0 * 1000.0));
    }
}

